package com.diankangwo.util;

import cn.beecloud.BCEumeration.PAY_CHANNEL;
import cn.beecloud.BCEumeration.QR_PAY_MODE;
import cn.beecloud.BCPay;
import cn.beecloud.BeeCloud;
import cn.beecloud.bean.*;
import org.apache.log4j.Logger;

import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * Beecloud.cn pay 支付
 *
 * @author xiaoyu 使用该类必须实例化
 */
public class BeecloudPay {

    Logger log = Logger.getLogger(this.getClass());

    // returnUrl(商户根据自身系统指定)
    private String yeeWebReturnUrl;
    private String yeeWapReturnUrl;
    private String jdWebReturnUrl;
    private String jdWapReturnUrl;
    private String kqReturnUrl;
    private String aliWebReturnUrl;
    private String aliWapReturnUrl;
    private String unWebReturnUrl;
    private String unWapReturnUrl;
    private String bdReturnUrl;

    // 微信 公众号id(读取配置文件conf.properties)及微信 redirec_uri
    private String wxJSAPAppId;
    private String wxJSAPIRedirectUrl;
    private String encodedWSJSAPIRedirectUrl;

    @SuppressWarnings("deprecation")
    public BeecloudPay() {
        Properties prop = LoadPropertyUtil.loadProperty("beecloudPay.properties");
        // 获取项目 APP ID 和 APP Secret
        String appID = prop.get("appId").toString();
        String appSecret = prop.get("appSecret").toString();
        String MasterSecret = prop.get("MasterSecret").toString();
        String TestSecret = prop.get("TestSecret").toString();
        // 获取微信配置
        wxJSAPAppId = prop.get("wxJSAPIAppId").toString();
        wxJSAPIRedirectUrl = prop.getProperty("wxJSAPIRedirectUrl");
        encodedWSJSAPIRedirectUrl = URLEncoder.encode(wxJSAPIRedirectUrl);
        // 支付回调地址
        yeeWebReturnUrl = prop.getProperty("yeeWebReturnUrl");
        yeeWapReturnUrl = prop.getProperty("yeeWapReturnUrl");
        jdWebReturnUrl = prop.getProperty("jdWebReturnUrl");
        jdWapReturnUrl = prop.getProperty("jdWapReturnUrl");
        kqReturnUrl = prop.getProperty("kqReturnUrl");
        aliWebReturnUrl = prop.getProperty("aliWebReturnUrl");
        aliWapReturnUrl = prop.getProperty("aliWapReturnUrl");
        unWebReturnUrl = prop.getProperty("unWebReturnUrl");
        unWapReturnUrl = prop.getProperty("unWapReturnUrl");
        bdReturnUrl = prop.getProperty("bdReturnUrl");
        // 注册支付信息
        BeeCloud.registerApp(appID, TestSecret, appSecret, MasterSecret);
    }

    /**
     * 微信扫码
     *
     * @param totalFee 订单总金额，只能为整数，单位为分，例如1，(必填)
     * @param billNo   商户订单号，8到20个字符内，数字和/或字母组合，确保在商户系统中唯一，例如(201506101035040000001),
     *                 (必填)
     * @param title    订单标题， 32个字节内，最长支持16个汉字，(必填)
     * @return 正确状态调用getCodeUrl()方法返回二维码字符串，返回code
     * url的格式为：weixin://wxpay/bizpayurl?sr=XXXXX。 请商户调用第三方库将返回的code
     * url生成二维码图片。 该模式链接较短，生成的二维码打印到结账小票上的识别率较高。 错误状态记录日志并返回null
     * @throws InterruptedException
     */
    public String wechatQrsPay(Integer totalFee, String billNo, String title) throws InterruptedException, BCException {
        BCOrder param = new BCOrder(PAY_CHANNEL.WX_NATIVE, totalFee, billNo, title);
        param.setBillTimeout(180);

        BCOrder bcPayResult = BCPay.startBCPay(param);
        if (bcPayResult.getChannel().ordinal() == 0) {
            // 正确状态调用getCodeUrl()方法返回二维码字符串，返回code
            // url的格式为：weixin://wxpay/bizpayurl?sr=XXXXX。
            // 请商户调用第三方库将返回的code url生成二维码图片。
            // 该模式链接较短，生成的二维码打印到结账小票上的识别率较高。
            log.debug("wechat qrs pay reutrn code url =" + bcPayResult.getCodeUrl());
            log.debug("wechat qrs pay return object id =" + bcPayResult.getObjectId());
            Thread.sleep(5000);
            return bcPayResult.getCodeUrl();
        } else {
            // handle the error message as you wish !
            log.error("微信扫码支付错误：" + bcPayResult.getMessageDetail());
            return null;
        }
    }

    /**
     * 微信公众号
     *
     * @param totalFee 订单总金额，只能为整数，单位为分，例如1，(必填)
     * @param billNo   商户订单号，8到20个字符内，数字和/或字母组合，确保在商户系统中唯一，例如(201506101035040000001),
     *                 (必填)
     * @param title    订单标题， 32个字节内，最长支持16个汉字，(必填)
     * @return 正确状态调用getWxJSAPIMap()方法返回jsapi map对象；错误状态记录日志并返回null
     * @throws InterruptedException
     */
    public Map<String, String> wechatJSAPIPay(Integer totalFee, String billNo, String title)
            throws InterruptedException, BCException {
        String redirectUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + wxJSAPAppId
                + "&redirect_uri=" + encodedWSJSAPIRedirectUrl
                + "&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";
        log.debug("wx jsapi redirct url:" + redirectUrl);
        System.out.println(redirectUrl);
        BCOrder param = new BCOrder(PAY_CHANNEL.WX_JSAPI, totalFee, billNo, title);
        param.setOpenId("openId"); // [微信公众号支付(WX_JSAPI)必填,(选填)]

        BCOrder bcPayResult = BCPay.startBCPay(param);
        if (bcPayResult.getChannel().ordinal() == 0) {
            // 正确状态调用getWxJSAPIMap()方法返回jsapi map对象。
            log.debug("wechat return jspai = " + bcPayResult.getWxJSAPIMap());
            Thread.sleep(5000);
            return bcPayResult.getWxJSAPIMap();
        } else {
            // handle the error message as you wish !
            log.error("微信公众号支付错误：" + bcPayResult.getMessageDetail());
            return null;
        }
    }

    /**
     * 银联网页
     *
     * @param totalFee 订单总金额，只能为整数，单位为分，例如1，(必填)
     * @param billNo   商户订单号，8到20个字符内，数字和/或字母组合，确保在商户系统中唯一，例如(201506101035040000001),
     *                 (必填)
     * @param title    订单标题， 32个字节内，最长支持16个汉字，(必填)
     * @return 正确状态返回HTML，错误状态记录日志并返回null
     * @throws InterruptedException
     */
    public String unionPay(Integer totalFee, String billNo, String title) throws InterruptedException, BCException {
        BCOrder param = new BCOrder(PAY_CHANNEL.UN_WEB, totalFee, billNo, title);
        param.setReturnUrl(unWebReturnUrl);
        param.setBillTimeout(180);

        BCOrder bcPayResult = BCPay.startBCPay(param);
        if (bcPayResult.getChannel().ordinal() == 0) {
            log.debug("union pay return object id=" + bcPayResult.getObjectId());
            log.debug("union pay return html = " + bcPayResult.getHtml());
            Thread.sleep(5000);
            return bcPayResult.getHtml();
        } else {
            // handle the error message as you wish !
            log.error("银联网页支付错误：" + bcPayResult.getMessageDetail());
            return null;
        }
    }

    /**
     * 阿里网页调用
     *
     * @param totalFee 订单总金额，只能为整数，单位为分，例如1，(必填)
     * @param billNo   商户订单号，8到20个字符内，数字和/或字母组合，确保在商户系统中唯一，例如(201506101035040000001),
     *                 (必填)
     * @param title    订单标题， 32个字节内，最长支持16个汉字，(必填)
     * @param optional 附加数据，用户自定义的参数，将会在webhook通知中原样返回，该字段主要用于商户携带订单的自定义数据(选填)
     * @return 正确状态返回URL，错误状态记录日志并返回null
     * @throws InterruptedException
     */
    public String aliPay(Integer totalFee, String billNo, String title, Map<String, Object> optional)
            throws InterruptedException, BCException {
        BCOrder param = new BCOrder(PAY_CHANNEL.ALI_WEB, totalFee, billNo, title);
        param.setReturnUrl(aliWebReturnUrl);
        param.setBillTimeout(180);
        param.setOptional(optional);

        BCOrder bcPayResult = BCPay.startBCPay(param);
        if (bcPayResult.getChannel().ordinal() == 0) {

            log.debug("ali pay return html =" + bcPayResult.getHtml());
            return bcPayResult.getUrl();
        } else {
            // handle the error message as you wish !
            log.error("阿里网页调用错误：" + bcPayResult.getMessageDetail());
            return null;
        }
    }

    /**
     * 阿里扫码支付
     *
     * @param totalFee 订单总金额，只能为整数，单位为分，例如1，(必填)
     * @param billNo   商户订单号，8到20个字符内，数字和/或字母组合，确保在商户系统中唯一，例如(201506101035040000001),
     *                 (必填)
     * @param title    订单标题， 32个字节内，最长支持16个汉字，(必填)
     * @return 正确状态返回HTML网页；错误状态记录日志并返回null
     * @throws InterruptedException
     */
    public String aliQrPay(Integer totalFee, String billNo, String title) throws InterruptedException, BCException {
        BCOrder param = new BCOrder(PAY_CHANNEL.ALI_QRCODE, totalFee, billNo, title);
        param.setReturnUrl(aliWapReturnUrl);
        param.setQrPayMode(QR_PAY_MODE.MODE_FRONT);
        param.setBillTimeout(120);

        BCOrder bcPayResult = BCPay.startBCPay(param);
        if (bcPayResult.getChannel().ordinal() == 0) {
            log.debug("ali Qr pay object id=" + bcPayResult.getObjectId());
            Thread.sleep(5000);
            log.debug("ali Qr pay url = " + bcPayResult.getUrl());
            log.debug("ali Qr pay html =" + bcPayResult.getHtml());
            // 使用url示例
            // System.out.println("<html><iframe width='420' height='330'
            // name='url' frameborder='0' src='" + bcPayResult.getUrl() +
            // "'></iframe</html>");
            return bcPayResult.getHtml();
        } else {
            // handle the error message as you wish !
            log.error("阿里扫码支付调用错误：" + bcPayResult.getMessageDetail());
            return null;
        }
    }

    /**
     * 阿里移动网页调用
     *
     * @param totalFee   订单总金额，只能为整数，单位为分，例如1，(必填)
     * @param billNo     商户订单号，8到20个字符内，数字和/或字母组合，确保在商户系统中唯一，例如(201506101035040000001),
     *                   (必填)
     * @param title      订单标题， 32个字节内，最长支持16个汉字，(必填)
     * @param returnType 自定义返回类型：getUrl：返回跳转URL；getHtml：返回网页;默认返回HTML
     * @return 正确状态返回getUrl或getHtml；错误状态记录日志并返回null
     * @throws InterruptedException
     */
    public String aliwapPay(Integer totalFee, String billNo, String title, String returnType)
            throws InterruptedException, BCException {
        BCOrder param = new BCOrder(PAY_CHANNEL.ALI_WAP, totalFee, billNo, title);
        param.setBillTimeout(120);

        BCOrder bcPayResult = BCPay.startBCPay(param);
        if (bcPayResult.getChannel().ordinal() == 0) {
            // 正确状态调用getHtml()方法或者getUrl()方法，getHtml()方法返回html,如将html输出至页面，即可开始支付。
            // getUrl()方法返回支付宝跳转url,推荐使用html
            log.debug("阿里移动网页 object id = " + bcPayResult.getObjectId());
            if (returnType.equals("getUrl")) {
                log.debug("阿里移动网页支付跳转URL：" + bcPayResult.getUrl());
                return bcPayResult.getUrl();
            } else if (returnType.equals("getHtml")) {
                log.debug("阿里移动网页支付输出网页");
                log.debug(bcPayResult.getHtml());
                return bcPayResult.getHtml();
            } else {
                return bcPayResult.getHtml();
            }
        } else {
            // handle the error message as you wish !
            log.error("阿里移动网页调用错误：" + bcPayResult.getMessageDetail());
            return null;
        }
    }

    /**
     * 快钱网页调用
     *
     * @param totalFee 订单总金额，只能为整数，单位为分，例如1，(必填)
     * @param billNo   商户订单号，8到20个字符内，数字和/或字母组合，确保在商户系统中唯一，例如(201506101035040000001),
     *                 (必填)
     * @param title    订单标题， 32个字节内，最长支持16个汉字，(必填)
     * @return 正确状态返回HTML网页；错误状态记录日志并返回null
     * @throws InterruptedException
     */
    public String kqWebPay(Integer totalFee, String billNo, String title) throws InterruptedException, BCException {
        BCOrder param = new BCOrder(PAY_CHANNEL.KUAIQIAN_WEB, totalFee, billNo, title);
        param.setBillTimeout(120);
        param.setReturnUrl(kqReturnUrl);

        BCOrder bcPayResult = BCPay.startBCPay(param);
        if (bcPayResult.getChannel().ordinal() == 0) {
            // 正确状态调用getHtml()方法，getHtml()方法返回html,如将html输出至页面，即可开始快钱网页支付。
            log.debug("快钱网页 object id =" + bcPayResult.getObjectId());
            log.debug("快钱网页:");
            log.debug(bcPayResult.getHtml());
            Thread.sleep(5000);
            return bcPayResult.getHtml();
        } else {
            // handle the error message as you wish !
            log.error("快钱网页调用错误：" + bcPayResult.getMessageDetail());
            return null;
        }
    }

    /**
     * 快钱移动网页调用
     *
     * @param totalFee 订单总金额，只能为整数，单位为分，例如1，(必填)
     * @param billNo   商户订单号，8到20个字符内，数字和/或字母组合，确保在商户系统中唯一，例如(201506101035040000001),
     *                 (必填)
     * @param title    订单标题， 32个字节内，最长支持16个汉字，(必填)
     * @return 正确状态调用返回HTML；错误状态记录日志并返回null
     * @throws InterruptedException
     */
    public String kqWapPay(Integer totalFee, String billNo, String title) throws InterruptedException, BCException {
        BCOrder param = new BCOrder(PAY_CHANNEL.KUAIQIAN_WAP, totalFee, billNo, title);
        param.setBillTimeout(120);

        BCOrder bcPayResult = BCPay.startBCPay(param);
        if (bcPayResult.getChannel().ordinal() == 0) {
            // 正确状态调用getHtml()方法，getHtml()方法返回html,如将html输出至页面，即可开始快钱移动网页支付
            log.debug("快钱移动网页 object id =" + bcPayResult.getObjectId());
            log.debug("快钱移动网页:");
            log.debug(bcPayResult.getHtml());
            Thread.sleep(5000);
            return bcPayResult.getHtml();
        } else {
            // handle the error message as you wish !
            log.error("快钱移动网页调用错误：" + bcPayResult.getMessageDetail());
            return null;
        }
    }

    /**
     * 京东网页调用
     *
     * @param totalFee 订单总金额，只能为整数，单位为分，例如1，(必填)
     * @param billNo   商户订单号，8到20个字符内，数字和/或字母组合，确保在商户系统中唯一，例如(201506101035040000001),
     *                 (必填)
     * @param title    订单标题， 32个字节内，最长支持16个汉字，(必填)
     * @return 正确状态返回HTML；错误状态记录日志并返回null
     * @throws InterruptedException
     */
    public String jdWebPay(Integer totalFee, String billNo, String title) throws InterruptedException, BCException {
        BCOrder param = new BCOrder(PAY_CHANNEL.JD_WEB, totalFee, billNo, title);
        param.setReturnUrl(jdWebReturnUrl); // jdReturnUrl

        BCOrder bcPayResult = BCPay.startBCPay(param);
        if (bcPayResult.getChannel().ordinal() == 0) {
            // 正确状态调用getHtml()方法，getHtml()方法返回html,如将html输出至页面，即可开始京东网页支付
            log.debug("jd web object id =" + bcPayResult.getObjectId());
            log.debug("京东网页支付：");
            log.debug(bcPayResult.getHtml());
            Thread.sleep(5000);
            return bcPayResult.getHtml();
        } else {
            // handle the error message as you wish !
            log.error("京东网页调用错误：" + bcPayResult.getMessageDetail());
            return null;
        }
    }

    /**
     * 京东移动网页调用
     *
     * @param totalFee 订单总金额，只能为整数，单位为分，例如1，(必填)
     * @param billNo   商户订单号，8到20个字符内，数字和/或字母组合，确保在商户系统中唯一，例如(201506101035040000001),
     *                 (必填)
     * @param title    订单标题， 32个字节内，最长支持16个汉字，(必填)
     * @return 正确状态返回HTML；失败状态记录日志并返回null
     * @throws InterruptedException
     */
    public String jdWapPay(Integer totalFee, String billNo, String title) throws InterruptedException, BCException {
        BCOrder param = new BCOrder(PAY_CHANNEL.JD_WAP, totalFee, billNo, title);
        param.setReturnUrl(jdWapReturnUrl); // jdReturnUrl

        BCOrder bcPayResult = BCPay.startBCPay(param);
        if (bcPayResult.getChannel().ordinal() == 0) {
            // 正确状态调用getHtml()方法，getHtml()方法返回html,如将html输出至页面，即可开始京东网页支付
            log.debug("JD pay object id =" + bcPayResult.getObjectId());
            log.debug("京东移动网页支付返回HTML");
            log.debug(bcPayResult.getHtml());
            Thread.sleep(5000);
            return bcPayResult.getHtml();
        } else {
            // handle the error message as you wish !
            log.error("京东移动网页调用错误：" + bcPayResult.getMessageDetail());
            return null;
        }
    }

    /**
     * 易宝网页调用
     *
     * @param totalFee   订单总金额，只能为整数，单位为分，例如1，(必填)
     * @param billNo     商户订单号，8到20个字符内，数字和/或字母组合，确保在商户系统中唯一，例如(201506101035040000001),
     *                   (必填)
     * @param title      订单标题， 32个字节内，最长支持16个汉字，(必填)
     * @param returnType 自定义返回类型：getUrl:返回跳转URL；getHtml：返回html网页，默认返回HTML
     * @return 成功状态返回URL或HTML；错误状态记录日志并返回null
     * @throws InterruptedException
     */
    public String yeeWebPay(Integer totalFee, String billNo, String title, String returnType)
            throws InterruptedException, BCException {
        BCOrder param = new BCOrder(PAY_CHANNEL.YEE_WEB, totalFee, billNo, title);
        param.setReturnUrl(yeeWebReturnUrl);
        param.setBillTimeout(180);

        BCOrder bcPayResult = BCPay.startBCPay(param);
        if (bcPayResult.getChannel().ordinal() == 0) {
            // 正确状态调用getHtml()方法或者getUrl()方法，getHtml()方法返回html,如将html输出至页面，即可开始支付。
            // getUrl()方法返回跳转url,推荐使用html。
            log.debug("yee web object id:" + bcPayResult.getObjectId());
            Thread.sleep(5000);
            if (returnType.equals("getUrl")) {
                log.debug("易宝网页调用返回URL：" + bcPayResult.getUrl());
                return bcPayResult.getUrl();
            } else if (returnType.equals("getHtml")) {
                log.debug("易宝网页调用返回HTML");
                log.debug(bcPayResult.getHtml());
                return bcPayResult.getHtml();
            } else {
                return bcPayResult.getHtml();
            }
        } else {
            // handle the error message as you wish !
            log.error("易宝网页调用错误：" + bcPayResult.getMessageDetail());
            return null;
        }
    }

    /**
     * 易宝移动网页调用
     *
     * @param totalFee 订单总金额，只能为整数，单位为分，例如1，(必填)
     * @param billNo   商户订单号，8到20个字符内，数字和/或字母组合，确保在商户系统中唯一，例如(201506101035040000001),
     *                 (必填)
     * @param title    订单标题， 32个字节内，最长支持16个汉字，(必填)
     * @return 正确状态返回跳转URL；错误则记录日志并返回null
     * @throws InterruptedException
     */
    public String yeeWapPay(Integer totalFee, String billNo, String title) throws InterruptedException, BCException {
        BCOrder param = new BCOrder(PAY_CHANNEL.YEE_WAP, totalFee, billNo, title);
        param.setReturnUrl(yeeWapReturnUrl);
        param.setBillTimeout(180);

        BCOrder bcPayResult = BCPay.startBCPay(param);
        if (bcPayResult.getChannel().ordinal() == 0) {
            // 正确状态调用getUrl()方法，getUrl()方法返回跳转url,如跳转至此url页面，即可开始支付。
            log.debug("yee wap object id:" + bcPayResult.getObjectId());
            log.debug("yee wap return url:" + bcPayResult.getUrl());
            Thread.sleep(5000);
            return bcPayResult.getUrl();
        } else {
            // handle the error message as you wish !
            log.error("易宝网页调用错误：" + bcPayResult.getMessageDetail());
            return null;
        }
    }

    /**
     * 百度网页调用
     *
     * @param totalFee 订单总金额，只能为整数，单位为分，例如1，(必填)
     * @param billNo   商户订单号，8到20个字符内，数字和/或字母组合，确保在商户系统中唯一，例如(201506101035040000001),
     *                 (必填)
     * @param title    订单标题， 32个字节内，最长支持16个汉字，(必填)
     * @return 正确状态返回支付url；错误状态记录日志并返回null
     * @throws InterruptedException
     */
    public String bdWebPay(Integer totalFee, String billNo, String title) throws InterruptedException, BCException {
        BCOrder param = new BCOrder(PAY_CHANNEL.BD_WEB, totalFee, billNo, title);
        param.setReturnUrl(bdReturnUrl);
        param.setBillTimeout(180);

        BCOrder bcPayResult = BCPay.startBCPay(param);
        if (bcPayResult.getChannel().ordinal() == 0) {
            // 正确状态调用getUrl()方法，getUrl()方法返回跳转url,如跳转至此url页面，即可开始支付。
            log.debug("百度网页调用" + bcPayResult.getObjectId());
            log.debug("百度网页调用" + bcPayResult.getUrl());
            Thread.sleep(5000);
            return bcPayResult.getUrl();
        } else {
            // handle the error message as you wish !
            log.error("百度网页调用错误：" + bcPayResult.getMessageDetail());
            return null;
        }
    }

    /**
     * * 百度移动网页调用
     *
     * @param totalFee 订单总金额，只能为整数，单位为分，例如1，(必填)
     * @param billNo   商户订单号，8到20个字符内，数字和/或字母组合，确保在商户系统中唯一，例如(201506101035040000001),
     *                 (必填)
     * @param title    订单标题， 32个字节内，最长支持16个汉字，(必填)
     * @return 正确状态返回支付URL；错误状态记录日志并返回null
     * @throws InterruptedException
     */
    public String bdWapPay(Integer totalFee, String billNo, String title) throws InterruptedException, BCException {
        BCOrder param = new BCOrder(PAY_CHANNEL.BD_WAP, totalFee, billNo, title);
        param.setReturnUrl(bdReturnUrl);// bdReturnUrl
        param.setBillTimeout(180);

        BCOrder bcPayResult = BCPay.startBCPay(param);
        if (bcPayResult.getChannel().ordinal() == 0) {
            // 正确状态调用getUrl()方法，getUrl()方法返回跳转url,如跳转至此url页面，即可开始支付。
            log.debug("百度移动网页调用:" + bcPayResult.getObjectId());
            log.debug("百度移动网页调用:" + bcPayResult.getUrl());
            Thread.sleep(5000);
            return bcPayResult.getUrl();
        } else {
            // handle the error message as you wish !
            log.error("百度移动网页调用错误：" + bcPayResult.getMessageDetail());
            return null;
        }
    }

    /**
     * * 批量打款(暂时只支持ALI)
     *
     * @param list 付款的详细数据{TransferData}的List集合
     *             付款方的支付宝账户名，支付宝名称
     * @return 正确调用返回跳转url, 跳转至支付url页面, 即可开始支付；错误则返回null
     */
    public String batchPayment(TransferParameter list) throws BCException {
        String bcPayResult = BCPay.startTransfer(list);
        if (list.getChannel().ordinal() == 0) {
            /**
             * 调用以下接口发起批量退款并将得到BCPayResult对象，
             * BCPayResult对象包含两种状态，正确状态和错误状态，正确状态的BCPayResult的type类型字符串为OK,
             * 对应值为0。 错误状态调用getErrMsg()方法返回错误信息。
             * 调用getErrDetail()方法返回具体错误信息，开发者可任意显示，打印，或者进行日志。
             * 正确状态调用getUrl()方法，getUrl()方法返回跳转url,如跳转至此url页面，即可开始支付。
             */
            return bcPayResult;
        } else {
            // handle the error message as you wish！
            return null;
        }

    }

    /**
     * 退款
     *
     * @param billNo    商户订单号， 32个字符内，数字和/或字母组合，确保在商户系统中唯一，(必填)
     * @param refundNo  商户退款单号 ， 格式为:退款日期(8位) + 流水号(3~24位)。不可重复，且退款日期必须是当天日期。
     *                  流水号可以接受数字或英文字符，建议使用数字，但不可接受“000”，例如：201506101035040000001 (必填)
     * @param refundFee 退款金额，只能为整数，单位为分，例如1，(必填)
     * @param optional  附加数据,用户自定义的参数，将会在webhook通知中原样返回，该字段主要用于商户携带订单的自定义数据，例如{"key1":
     *                  "value1","key2":"value2",...},(选填)
     * @return 阿里退款，跳转至退款url并输入支付密码完成退款；其他渠道退款，返回"退款成功"；失败返回null
     */
    public String BCRefundParamter(String billNo, String refundNo, Integer refundFee, Map<String, Object> optional) throws BCException {
        BCRefund param = new BCRefund(billNo, refundNo, refundFee);
        param.setOptional(optional);

        BCRefund result = BCPay.startBCRefund(param);
        if (result.getChannel().ordinal() == 0) {
            if (result.getAliRefundUrl() != null) {
                // 阿里退款，跳转至退款url并输入支付密码完成退款
                log.debug("阿里退款：" + result.getAliRefundUrl());
                return result.getAliRefundUrl();
            } else {
                // 其他渠道退款，返回"退款成功"
                log.debug("其他渠道退款，返回'退款成功'：" + result.getMessageDetail());
                return result.getMessageDetail();
            }
        } else {
            log.error("退款调用错误" + result.getMessageDetail());
            return null;
        }
    }

    /**
     * 订单查询
     *
     * @return 正确状态调用bcQueryResult.getBcOrders()方法返回订单(BCOrderBean)的list集合;
     * 调用者可任意遍历，显示这个订单的list对象; 错误返回null
     */
    public List<BCOrder> BCQuery() throws BCException {
        BCQueryParameter param = new BCQueryParameter();
        param.setChannel(PAY_CHANNEL.ALI);
        /*
         * 发起订单查询后返回BCQueryResult对象，BCQueryResult对象包含两种状态，正确状态和错误状态，
		 * 正确状态的BCQueryResult的type类型字符串为OK, 对应值为0。 错误状态调用getErrMsg()方法返回错误信息。
		 * 调用getErrDetail()方法返回具体错误信息，开发者可任意显示，打印，或者进行日志。
		 * 正确状态调用bcQueryResult.getBcOrders()方法返回订单(BCOrderBean)的list集合。
		 * 调用者可任意遍历，显示这个订单的list对象。
		 */
        List<BCOrder> bcQueryResult = BCPay.startQueryBill(param);
        return bcQueryResult;

    }

    /**
     * 退款查询
     *
     * @return 正确状态调用bcQueryResult.getBcRefundList()方法返回退款记录(BCRefundBean)
     * 的list集合。 调用者可任意遍历，显示这个退款记录的list对象。
     * 错误状态调用getErrMsg()方法记录错误信息，返回null
     */
    public List<BCRefund> BCRefundQuery() throws BCException {
        BCRefundQueryParameter param = new BCRefundQueryParameter();
        param.setChannel(PAY_CHANNEL.ALI);
        /*
         * 发起退款查询将得到BCQueryResult对象，BCQueryResult对象包含两种状态，正确状态和错误状态，
		 * 正确状态的BCQueryResult的type类型字符串为OK, 对应值为0。 错误状态调用getErrMsg()方法返回错误信息。
		 * 调用getErrDetail()方法返回具体错误信息，开发者可任意显示，打印，或者进行日志。
		 * 正确状态调用bcQueryResult.getBcRefundList()方法返回退款记录(BCRefundBean)的list集合。
		 * 调用者可任意遍历，显示这个退款记录的list对象。
		 */
        List<BCRefund> bcQueryResult = BCPay.startQueryRefund(param);
        return bcQueryResult;

    }

    /**
     * 退款状态查询
     *
     * @param channel  (必填) 渠道类型， 根据不同场景选择不同的支付方式，包含： YEE 易宝 WX 微信 KUAIQIAN 快钱 BD 百度
     * @param refundNo (必填)商户退款单号， 格式为:退款日期(8位) + 流水号(3~24 位)。不可重复，且退款日期必须是当天日期。
     *                 流水号可以接受数字或英文字符，建议使用数字，但不可接受“000”。
     * @return 退款状态(Success, Processing, Fail...)。调用者可任意处理这个值。
     */
    public String BCqueryStatusResult(PAY_CHANNEL channel, String refundNo) throws BCException {
        /*
		 * 调用以下接口发起退款状态查询并将得到BCQueryStatusResult对象，
		 * BCQueryStatusResult对象包含两种状态，正确状态和错误状态，
		 * 正确状态的BCQueryStatusResult的type类型字符串为OK, 对应值为0。
		 * 错误状态调用getErrMsg()方法返回错误信息。
		 * 调用getErrDetail()方法返回具体错误信息，开发者可任意显示，打印，或者进行日志。 调用参数中，channel参数包含以下取值：
		 * YEE 易宝 WX 微信 KUAIQIAN 快钱 BD 百度
		 */
        String result = BCPay.startRefundUpdate(channel, refundNo);
        return result;
    }

    /**
     * 支付订单查询(指定ID)
     *
     * @param id 订单号
     * @return 正确状态返回该笔订单对象；否则记录错误日志，并返回null
     */
    public BCOrder BCQueryById(String id) throws  BCException {
		/*
		 * 调用以下接口发起支付订单查询(指定ID)并将得到BCQueryResult对象，
		 * BCQueryResult对象包含两种状态，正确状态和错误状态， 正确状态的BCQueryResult的type类型字符串为OK,
		 * 对应值为0。 错误状态调用getErrMsg()方法返回错误信息。
		 * 调用getErrDetail()方法返回具体错误信息，开发者可任意显示，打印，或者进行日志。
		 */
        BCOrder result = BCPay.startQueryBillById(id);
        if (result.getChannel().ordinal() == 0) {
            // 正确状态调用getOrder()方法返回该笔订单对象。
            log.debug("支付订单查询：id=" + id);
            return result;
        } else {
            log.error("支付订单查询(指定ID)调用错误" + result.getMessageDetail());
            return null;
        }
    }

    /**
     * 退款订单查询(指定ID)
     *
     * @param id 退款订单ID
     * @return 正确状态返回该笔退款记录对象；错误状态记录日志，返回null
     */
    public BCRefund BCQueryRefundById(String id) throws  BCException {
		/*
		 * 调用以下接口发起支付订单查询(指定ID)并将得到BCQueryResult对象，
		 * BCQueryResult对象包含两种状态，正确状态和错误状态， 正确状态的BCQueryResult的type类型字符串为OK,
		 * 对应值为0。 错误状态调用getErrMsg()方法返回错误信息。
		 * 调用getErrDetail()方法返回具体错误信息，开发者可任意显示，打印，或者进行日志。
		 */
        BCRefund result = BCPay.startQueryRefundById(id);
        if (result.getChannel().ordinal() == 0) {
            // 正确状态调用getRefund()方法返回该笔退款记录对象。
            log.debug("退款订单查询：id=" + id);
            return result;
        } else {
            log.error("退款订单查询(指定ID)调用错误" + result.getMessageDetail());
            return null;
        }
    }

}
